﻿using System;
using System.Collections.Generic;
using System.Threading;
using NUnit;
using NUnit.Framework;
using Rhino.Mocks;
using System.Globalization;
using System.Resources;
using Microsoft.Practices.ServiceLocation;
using AutoMapper;

namespace mForum.Services.Test
{
    using mForum.Domain.DomainObject;
    using mForum.Domain.Repository;
    using mForum.Core.Messages;
    using mForum.Core.Messages.UserServiceMessages;
    using mForum.Services;
    using mForum.Resources;
    using mForum.Core.DataTransferObject;
    using mForum.Core.Infrastructure;
    using mForum.Core.Infrastructure.Resource;
    using mForum.Core.Infrastructure.IoC;
    using mForum.Infrastructure.AutoMapper;

    [TestFixture]
    public class UserServiceTest
    {
        private List<User> _fakeUserList;
        private UserService _userService;
        private IUserRepository _userRepository;
        private ResourceManager _resourceManager;
        private ResourceManagerFactory _resourceManagerFactory;
        private IServiceLocator _serviceLocator;
        private IUnitOfWork _unitOfWork;

        [SetUp]
        public void SetUp()
        {
            _resourceManagerFactory = new ResourceManagerFactory();
            _resourceManager = _resourceManagerFactory.CreateResourceManager();
            ResourceHelper.Initialize(_resourceManager);

            _serviceLocator = MockRepository.GenerateMock<IServiceLocator>();
            IoC.InitializeWith(_serviceLocator);

            Mapper.Initialize(x => x.AddProfile<DefaultProfile>());

            InitializeFakeUserList();

            _userRepository = MockRepository.GenerateMock<IUserRepository>();
            _userRepository.Stub(f => f.FindUserByUsername("Test")).Return(_fakeUserList[0]);
            _userRepository.Stub(f => f.FindUserByUsername("Test2")).Return(_fakeUserList[1]);
            _userRepository.Stub(f => f.FindUserByUsername("Test3")).Return(_fakeUserList[2]);
            _userRepository.Stub(f => f.FindUserByUsername("Test4")).Return(_fakeUserList[3]);

            _userRepository.Stub(f => f.All()).Return(_fakeUserList);

            _unitOfWork = MockRepository.GenerateMock<IUnitOfWork>();
            _userService = new UserService(_userRepository, _unitOfWork);
        }

        [Test]
        [TestCase("Test","asdzxc", true)]
        [TestCase("Test","zxcas", false)]
        [TestCase("Test6", "qweasd", false)]
        [TestCase("Test2", "qwerty", false)]
        public void can_validate_user(string username, string password, bool expectedResult)
        {
            LogOnDTO logOnDto = new LogOnDTO()
            {
                Username = username,
                Password = password
            };

            LogOnResponse result = _userService.ValidateUser(new LogOnRequest() { LogOnDTO = logOnDto });

            Assert.AreEqual(expectedResult, result.isValidated);
        }

        [Test]
        [ExpectedException(typeof(Exception))]
        public void can_not_register_if_user_exists()
        {
            RegisterDTO registerDTO = Mapper.Map<User, RegisterDTO>(_fakeUserList[0]);

            _userService.CreateUser(new RegisterRequest() { RegisterDTO = registerDTO });
        }


        [Test]
        public void can_register_new_user()
        {
            RegisterDTO registerDTO = new RegisterDTO()
            {
                Username = "tescik",
                Password = "lolol",
                Email = "lolek@op.pl",
                PasswordQuestion = "Test question",
                PasswordAnswer = "lol"
            };

            RegisterResponse response = _userService.CreateUser(new RegisterRequest() { RegisterDTO = registerDTO });

            Assert.AreEqual(registerDTO.Username, response.UserDTO.Username);
            Assert.AreEqual(registerDTO.Password, response.UserDTO.Password);
            Assert.AreEqual(registerDTO.PasswordAnswer, response.UserDTO.PasswordAnswer);
            Assert.AreEqual(registerDTO.PasswordQuestion, response.UserDTO.PasswordQuestion);
        }

        [Test]
        [TestCase("Test")]
        [TestCase("Test2")]
        [TestCase("Test3")]
        [TestCase("Test4")]
        public void can_delete_existing_user(string username)
        {
            _userService.DeleteUser(new DeleteUserRequest() { Username = username });
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void can_not_delete_non_existing_user()
        {
            string username = "Test56";

            _userService.DeleteUser(new DeleteUserRequest() { Username = username });
        }

        [Test]
        [TestCase("Test")]
        [TestCase("Test2")]
        [TestCase("Test3")]
        [TestCase("Test4")]
        public void can_get_user_by_username(string username)
        {
            GetUserByUsernameResponse response = _userService.GetUserByUsername(new GetUserByUsernameRequest() { Username = username });

            Assert.AreEqual(username, response.UserDTO.Username);
        }

        private void InitializeFakeUserList()
        {
            _fakeUserList = new List<User>();
            _fakeUserList.Add(new User()
                                        {
                                            Username = "Test",
                                            Password = "asdzxc",
                                            Email = "test@op.pl",
                                            PasswordAnswer = "dog",
                                            PasswordQuestion = "What's your favourite animal?",
                                            CreatedDate = DateTime.Now,
                                            LastLoginDate = DateTime.Now,
                                            LastActivityDate = DateTime.Now,
                                            isLockedOut = false
                                        });

            _fakeUserList.Add(new User()
                                        {
                                            Username = "Test2",
                                            Password = "qwerty",
                                            Email = "test@gmail.pl",
                                            PasswordAnswer = "cat",
                                            PasswordQuestion = "What's your favourite animal?",
                                            CreatedDate = DateTime.Now.AddDays(-1),
                                            LastLoginDate = DateTime.Now.AddHours(-2),
                                            LastActivityDate = DateTime.Now.AddHours(-1),
                                            isLockedOut = true
                                        });

            _fakeUserList.Add(new User()
                                        {
                                            Username = "Test3",
                                            Password = "asdzxc",
                                            Email = "test@lol.pl",
                                            PasswordAnswer = "lol",
                                            PasswordQuestion = "What's your favourite animal?",
                                            CreatedDate = DateTime.Now.AddDays(-2),
                                            LastLoginDate = DateTime.Now.AddMinutes(-4),
                                            LastActivityDate = DateTime.Now.AddMinutes(-1),
                                            isLockedOut = false
                                        });

            _fakeUserList.Add(new User()
                                        {
                                            Username = "Test4",
                                            Password = "qwerty",
                                            Email = "test@haha.pl",
                                            PasswordAnswer = "elephant",
                                            PasswordQuestion = "What's your favourite animal?",
                                            CreatedDate = DateTime.Now.AddDays(-1),
                                            LastLoginDate = DateTime.Now.AddMinutes(-3),
                                            LastActivityDate = DateTime.Now.AddMinutes(-2),
                                            isLockedOut = false
                                        });
        }
    }
}
